home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Src / Key / KeyTables.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-22  |  26.8 KB  |  1,360 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     keytables.c
  5.  
  6.     DESCRIPTION
  7.     Management for Key-Hashing tables
  8.  
  9.     NOTES
  10.     original from M.Dillon
  11.  
  12.     for the first(!) call of any function of that module,
  13.     the corresponding HASH-table must be clean (setmem(...,0))
  14.  
  15.     BUGS
  16.     thousands - but where
  17.     there may be some inconsistencies
  18.  
  19.     TODO
  20.     new method for management of hashes
  21.  
  22.     EXAMPLES
  23.  
  24.     SEE ALSO
  25.     keycodes.c keycom.c keycontrol.c
  26.  
  27.     INDEX
  28.  
  29.     HISTORY
  30.     14-Dec-92  b_null created
  31.     15-Dez-92  b_null modified
  32.     15-Dez-92  b_null docs updated, some checks added
  33.     16-Dez-92  b_null documented
  34.     16 Jun 93  b_null introduced "struct keyspec"
  35.     29-Jun-94  b_null Docs updated
  36.     24-09-94   b_null disabled keyload/keysave
  37.     $Date: 1994/09/20 11:09:43 $ last update
  38.  
  39. ******************************************************************************/
  40.  
  41. /**************************************
  42.         Includes
  43. **************************************/
  44. #define  KEY_INTERNAL
  45. #include "defs.h"
  46. #include <devices/keymap.h>
  47. #include <devices/console.h>
  48. #include "keyhashes.h"
  49.  
  50.  
  51. /**************************************
  52.         Globale Variable
  53. **************************************/
  54.  
  55. //Prototype void   keyload      (KEYTABLE * kt, char * name);
  56. //Prototype void   keysave      (KEYTABLE * kt, char * name);
  57. Prototype int     loadkeys    (KEYTABLE * kt, FILE * fi, int * lineno);
  58. Prototype int     savekeys    (KEYTABLE * kt, FILE * fo);
  59. Prototype HASH * findhash    (KEYTABLE * kt, KEYSPEC *ks,       UBYTE *, BOOL *);
  60. Prototype APTR     keyspec2macro    (KEYTABLE * kt,              const UBYTE *);
  61. Prototype int     resethash    (KEYTABLE * kt);
  62. Prototype int     unmapkey    (KEYTABLE * kt, const UBYTE *key);
  63. Prototype int     mapkey     (KEYTABLE * kt, const UBYTE *key, const UBYTE *value, const UBYTE *help);
  64. Prototype int     remhash    (KEYTABLE * kt, KEYSPEC *ks);
  65. Prototype int     addhash    (KEYTABLE * kt, KEYSPEC *ks, const UBYTE *comm, const UBYTE *help);
  66. Prototype void     dealloc_hash    (KEYTABLE * kt);
  67.  
  68. Prototype KEYTABLE * get_keytable    (char * name);
  69. Prototype KEYTABLE * new_keytable    (char * name, int defaults);
  70. Prototype void         delete_keytable (KEYTABLE * kt, int force);
  71.  
  72. Prototype void         exit_keytables (void);
  73.  
  74. /**************************************
  75.       Interne Defines & Strukturen
  76. **************************************/
  77.  
  78. #ifndef QUAL_UP
  79. #define QUAL_UP 0x80
  80. #endif
  81.  
  82.  
  83. /**************************************
  84.         Interne Variable
  85. **************************************/
  86. /* extern TWOSTRINGS defmap[]; */
  87. #include "defmap.h"
  88.  
  89.  
  90. /* this is the list of all keytables */
  91. static struct MinList _KeyTables;
  92. APTR KeyRoot   = NULL;
  93. APTR KeyTables = NULL;
  94.  
  95.  
  96. /**************************************
  97.        Interne Prototypes
  98. **************************************/
  99.  
  100.  
  101.  
  102. /*****************************************************************************
  103.  
  104.     NAME
  105.     freehash
  106.  
  107.     PARAMETER
  108.     HASH * hash
  109.  
  110.     RESULT
  111.     the hash->next entry if existing
  112.     NULL if hash == NULL
  113.  
  114.     RETURN
  115.     HASH *
  116.  
  117.     DESCRIPTION
  118.     free a hash-entry and all associated data
  119.  
  120.     NOTES
  121.     the free'd hash must not be entry in a hashtable,
  122.     as we do not take care of any refernces, but only
  123.     of hash, comm and help
  124.  
  125.     BUGS
  126.  
  127.     EXAMPLES
  128.  
  129.     SEE ALSO
  130.  
  131.     INTERNALS
  132.  
  133.     HISTORY
  134.     23 Jan 1993 b_null created
  135.  
  136. ******************************************************************************/
  137.  
  138. HASH * freehash (HASH * hash)
  139. {
  140.     HASH * next = NULL;
  141.  
  142.     if (hash) {
  143.     next = hash->next;
  144.     if (hash->comm) {
  145.         DeallocFunc (hash->comm);
  146.     } /* if */
  147.     if (hash->help) {
  148.         DeallocFunc (hash->help);
  149.     } /* if */
  150.     FreeFunc(hash, sizeof(HASH));
  151.     } /* if */
  152.  
  153.     return (next);
  154. } /* freehash */
  155.  
  156.  
  157.  
  158. /*****************************************************************************
  159.  
  160.     NAME
  161.     addhash
  162.  
  163.     PARAMETER
  164.     KEYTABLE    * kt
  165.     KEYSPEC     * ks
  166.     const UBYTE * comm
  167.     const UBYTE * help
  168.  
  169.     RESULT
  170.     success: RET_SUCC == ok; RET_FAIL == failure
  171.  
  172.     RETURN
  173.     int
  174.  
  175.     DESCRIPTION
  176.     create a new hash-entry for a known hash
  177.     if there is already an existing one with the same code/qual
  178.     simply change its command
  179.  
  180.     NOTES
  181.     that function is called by mapkey
  182.  
  183.     BUGS
  184.     WARNING : WE DO NOT LOOK FOR A SETTING OF help YET !!!
  185.  
  186.     EXAMPLES
  187.  
  188.     SEE ALSO
  189.  
  190.     INTERNALS
  191.     finde den hash-slot
  192.     falls der eintrag schon existiert, ersetze den comm
  193.     sonst erstelle einen neuen eintrag
  194.     falls nicht alles funktionierte, stelle den alten zustand wieder her
  195.  
  196.     HISTORY
  197.     14-Dec-92  b_null included & modified
  198.     16-Dec-92  b_null added handling of "nolink"
  199.  
  200. ******************************************************************************/
  201.  
  202. int addhash (KEYTABLE * kt, KEYSPEC * ks, const UBYTE * comm, const UBYTE * help)
  203. {
  204.     HASH ** p,
  205.       * hash;
  206.  /* APTR    oldcomm = NULL; */
  207.  
  208.     if (kt == NULL) {
  209.     return (RET_FAIL);
  210.     } /* if empty or missing table */
  211.  
  212.     hash = *(p = &KT_SLOT(kt,ks));
  213.  
  214.     while (hash) {
  215.     if (KS_MATCH_EXACT(&hash->key, ks)) {
  216.         goto newstr;
  217.     } /* if found old */
  218.     hash = *(p = &hash->next);
  219.     } /* while entries left */
  220.  
  221.     if (!(hash  = (HASH *)AllocFunc (sizeof (HASH), MEMF_ANY|MEMF_CLEAR))) {
  222.     SET_ABORTION( 1 );
  223.     return (RET_FAIL);
  224.     } /* if nomemory */
  225. /*    clrmem (hash, sizeof (HASH)); */
  226.  
  227.     hash->next = NULL;
  228.     KS_COPY(&hash->key,ks);
  229.  
  230. newstr:
  231.     /* oldcomm = hash->comm; */
  232.     DeallocFunc (hash->comm);
  233.     DeallocFunc (hash->help);
  234.  
  235.     hash->comm = DupFunc (comm, 0);
  236.     hash->help = DupFunc (help, 0);
  237.  
  238.     if ((!hash->comm) /* || (!hash->help) */ /* || (oldcomm == hash->comm) */) {
  239.     *p = freehash (hash);
  240.     return (RET_FAIL);
  241.     } /* if something went wrong */
  242.  
  243.     /* everything worked fine - insert it into the table */
  244.     *p = hash;
  245.     return (RET_SUCC);
  246. } /* addhash */
  247.  
  248.  
  249.  
  250. /*****************************************************************************
  251.  
  252.     NAME
  253.     remhash
  254.  
  255.     PARAMETER
  256.     KEYTABLE * kt
  257.     KEYSPEC  * ks
  258.  
  259.     RESULT
  260.     success:
  261.         RET_SUCC == ok;
  262.         RET_FAIL == failure or not found
  263.  
  264.     RETURN
  265.     int
  266.  
  267.     DESCRIPTION
  268.     delete an existing hashentry
  269.  
  270.     NOTES
  271.     that function is called by unmapkey
  272.  
  273.     BUGS
  274.  
  275.     EXAMPLES
  276.  
  277.     SEE ALSO
  278.  
  279.     INTERNALS
  280.     finde den hash-slot
  281.     falls der eintrag existiert, loesche ihn und seinen link
  282.     sonst mache gar nichts
  283.  
  284.     HISTORY
  285.     14-Dec-92  b_null included & modified
  286.     23-Jan-93  b_null used freehash
  287.  
  288. ******************************************************************************/
  289.  
  290. int remhash (KEYTABLE * kt, KEYSPEC * ks)
  291. {
  292.     HASH *  hash, /* current */
  293.      ** p;      /* previous */
  294.  
  295.     if (kt == NULL) {
  296.     return (RET_FAIL);
  297.     } /* if empty or missing table */
  298.  
  299.     hash = *(p = &KT_SLOT(kt,ks));
  300.     while (hash) {
  301.     if (KS_MATCH_EXACT(&hash->key, ks)) {
  302.         *p = freehash (hash);
  303.         return   (RET_SUCC);
  304.     } /* if found */
  305.     hash = *(p = &hash->next);
  306.     } /* while searching */
  307.  
  308.     /* not found: */
  309.     return (RET_FAIL);
  310. } /* remhash */
  311.  
  312.  
  313.  
  314. /*****************************************************************************
  315.  
  316.     NAME
  317.     mapkey
  318.  
  319.     PARAMETER
  320.     KEYTABLE    * kt
  321.     const UBYTE * key
  322.     const UBYTE * value
  323.     const UBYTE * help
  324.  
  325.     RESULT
  326.     success:
  327.         RET_FAIL == error
  328.         RET_OK   == everything ok
  329.  
  330.     RETURN
  331.     int
  332.  
  333.     DESCRIPTION
  334.     first abstraction for addhash
  335.     which uses an ascii-name
  336.  
  337.     NOTES
  338.     this function might call error()
  339.  
  340.     BUGS
  341.  
  342.     EXAMPLES
  343.  
  344.     SEE ALSO
  345.     addhash, unmapkey
  346.  
  347.     INTERNALS
  348.     falls es sich um einen gueltigen map handelt
  349.         belege ihn (neu)
  350.     sonst gebe eine fehlermeldung aus
  351.  
  352.     HISTORY
  353.     14-Dec-92  b_null included & modified
  354.     23-Jan-93  b_null void -> int
  355.  
  356. ******************************************************************************/
  357.  
  358. int mapkey (KEYTABLE * kt, const UBYTE * key, const UBYTE * value, const UBYTE *help)
  359. {
  360.     struct keyspec ks;
  361.  
  362.     if (get_codequal (key, &ks)) {
  363.     return (addhash (kt, &ks, value, help));
  364.     } else {
  365. DEFMESSAGE( _KEY_unknown_key, "%s:\nUnknown Key '%s'" )
  366.     error (_KEY_unknown_key, CommandName(), key);
  367.     }
  368.     return (RET_FAIL);
  369. } /* mapkey */
  370.  
  371.  
  372.  
  373. /*****************************************************************************
  374.  
  375.     NAME
  376.     unmapkey
  377.  
  378.     PARAMETER
  379.     KEYTABLE    * kt
  380.     const UBYTE * key
  381.  
  382.     RESULT
  383.     success:
  384.         RET_FAIL == error
  385.         RET_OK   == everything ok
  386.  
  387.     RETURN
  388.     int
  389.  
  390.     DESCRIPTION
  391.     first abstraction for remhash
  392.     which uses an ascii-name
  393.  
  394.     NOTES
  395.     this function might call error()
  396.  
  397.     BUGS
  398.  
  399.     EXAMPLES
  400.  
  401.     SEE ALSO
  402.     remhash, mapkey
  403.  
  404.     INTERNALS
  405.     falls es sich um einen gueltigen map handelt
  406.         loesche seine belegung
  407.     sonst gebe eine fehlermeldung aus
  408.  
  409.     HISTORY
  410.     14-Dec-92  b_null included & modified
  411.     23-Jan-93  b_null void -> int
  412.  
  413. ******************************************************************************/
  414.  
  415. int unmapkey (KEYTABLE * kt, const UBYTE * key)
  416. {
  417.     struct keyspec ks;
  418.  
  419.     if (get_codequal (key, &ks)) {
  420.     return (remhash (kt, &ks));
  421.     } else {
  422. DEFMESSAGE( _KEY_unknown_key, "%s:\nUnknown Key '%s'" )
  423.     error (_KEY_unknown_key, CommandName(), key);
  424.     }
  425.     return (RET_FAIL);
  426. } /* unmapkey */
  427.  
  428.  
  429.  
  430. /*****************************************************************************
  431.  
  432.     NAME
  433.     dealloc_hash
  434.  
  435.     PARAMETER
  436.     KEYTABLE * kt
  437.  
  438.     RESULT
  439.     -/-
  440.  
  441.     RETURN
  442.     void
  443.  
  444.     DESCRIPTION
  445.     frees all Hash-entries in a key-table
  446.  
  447.     NOTES
  448.  
  449.     BUGS
  450.  
  451.     EXAMPLES
  452.  
  453.     SEE ALSO
  454.  
  455.     INTERNALS
  456.     ueber allen hash-slots
  457.         loesche jeden eintrag des hash-slots
  458.  
  459.     HISTORY
  460.     14-Dec-92  b_null included & modified
  461.  
  462. ******************************************************************************/
  463.  
  464. void dealloc_hash ( KEYTABLE * kt )
  465. {
  466.     HASH * hash,
  467.      * hnext;  /* save ptr to the next entry when freeing the current */
  468.     WORD   i;
  469.  
  470.     if (kt == NULL) {
  471.     return;
  472.     } /* if empty or missing table */
  473.  
  474.     for (i = 0; i < HASHSIZE; i++) {
  475.     for (hash = kt->hash[i]; hash; hash = hnext) {
  476.         hnext = freehash (hash);
  477.     } /* for */
  478.     kt->hash[i] = NULL;
  479.     } /* for */
  480. } /* dealloc_hash */
  481.  
  482.  
  483.  
  484. /*****************************************************************************
  485.  
  486.     NAME
  487.     resethash
  488.  
  489.     PARAMETER
  490.     KEYTABLE * kt
  491.  
  492.     RESULT
  493.     success:
  494.         RET_FAIL == error (might have worked partially)
  495.         RET_OK   == everything ok
  496.  
  497.     RETURN
  498.     int
  499.  
  500.     DESCRIPTION
  501.     dealloc all entries of a hashtable and then
  502.     set its contents to default-values
  503.  
  504.     NOTES
  505.     the defaults are stored in an array
  506.     called defmap
  507.  
  508.     BUGS
  509.  
  510.     EXAMPLES
  511.  
  512.     SEE ALSO
  513.     mapkey, dealloc_hash
  514.  
  515.     INTERNALS
  516.     loesche die tabelle
  517.     solange noch ein gueltiger eintrag in defmap ist (und alles gutging)
  518.         erzeuge eine map fuer ihn
  519.  
  520.     HISTORY
  521.     14-Dec-92  b_null included
  522.     16-Dec-92  b_null documented
  523.  
  524. ******************************************************************************/
  525.  
  526. int resethash (KEYTABLE * kt)
  527. {
  528.     WORD i;
  529.  
  530.     if (kt == NULL) {
  531.     return (RET_FAIL);
  532.     } /* if empty or missing table */
  533.  
  534.     dealloc_hash (kt);
  535.  
  536.     for (i = 0; defmap[i].from; ++i) {
  537.     if (!mapkey (kt, defmap[i].from, defmap[i].to, NULL)) { /* ,defmap[i].help)) */
  538.         return (RET_FAIL);
  539.     } /* if error */
  540.     } /* for defmap-entries */
  541.  
  542.     return (RET_SUCC);
  543. } /* resethash */
  544.  
  545.  
  546.  
  547. /*****************************************************************************
  548.  
  549.     NAME
  550.     findhash
  551.  
  552.     PARAMETER
  553.     KEYTABLE *kt
  554.     KEYSPEC  *ks
  555.     UBYTE     *hint ; oder ULONG pkeys
  556.                ; additional info to be used if the key is unmapped
  557.     BOOL     *using_hint;
  558.  
  559.     RESULT
  560.     the hash-entry associated with code and qual
  561.  
  562.     RETURN
  563.     HASH *
  564.  
  565.     DESCRIPTION
  566.     simple searching
  567.  
  568.     NOTES
  569.     this routine is part of keyspec2macro
  570.  
  571.     BUGS
  572.  
  573.     EXAMPLES
  574.  
  575.     SEE ALSO
  576.     keyspec2macro
  577.  
  578.     INTERNALS
  579.     finde den richtigen slot
  580.     solange es noch eintraege in dem slot gibe, und der richtige nicht
  581.         gefunden ist,
  582.         gehe zum naechsten eintrag
  583.     wenn du was gefunden hast, gib es aus, sonst NULL
  584.  
  585.     HISTORY
  586.     16-Dec-92  b_null created
  587.     02-04-93   b_noll added defaulting
  588.     20-10-94   b_noll using_hint added
  589.  
  590. ******************************************************************************/
  591.  
  592. HASH * findhash (KEYTABLE *kt, KEYSPEC *ks, UBYTE *hint, BOOL *using_hint)
  593. {
  594.     HASH * hash;
  595.  
  596.     if (kt == NULL) {
  597.     return (NULL);
  598.     } /* if empty or missing table */
  599.  
  600.     /* PATCH_NULL [11 Mar 1994] : added for better recognition */
  601.     for (hash = KT_SLOT(kt,ks); hash; hash = hash->next) {
  602.     if (KS_MATCH_EXACT(&hash->key,ks)) {
  603.         return (hash);
  604.     } /* if */
  605.     } /* for */
  606.  
  607.     for (hash = KT_SLOT(kt,ks); hash; hash = hash->next) {
  608.     if (KS_MATCH_APPROX(&hash->key,ks)) {
  609.         return (hash);
  610.     } /* if */
  611.     } /* for */
  612.  
  613.     /* PATCH_NULL [02 Apr 1993] : we can not call that proc on unmapped keys yet >>> */
  614. #ifndef NOT_DEF
  615.     {
  616.     static HASH retdummy;      /* static, 'coz we return a ptr to that data */
  617.     static char rdchars[36];
  618.  
  619.     /* we have to create a dummy-Intuimessage and call RawKeyConvert with it */
  620.     struct InputEvent ie = { NULL, IECLASS_RAWKEY, 0, 0, 0, NULL, 0L,0L};
  621.     long        len;
  622.  
  623.     if (hint) {                       /* PATCH_NULL 27-06-94      */
  624.         strcpy (rdchars, hint);/* That dirty Hack is added */
  625.         goto findhash_dummyfound;        /* to reenable DeadKeys    */
  626.     } /* if */
  627.  
  628.     ie.ie_Code           = KS_CODE(ks);
  629.     ie.ie_Qualifier        = qual2iqual(KS_QUAL(ks));
  630.     /* ie.ie_position.ie_addr = (APTR)pkeys; */
  631.  
  632.     if (IsRawC(ks) && (len = RawKeyConvert (&ie, rdchars+1, 36-2, NULL) > 0)) { /* PATCH_NULL 27-06-94 changed ">" into ">=" to reenable Deadkeys */
  633. /* printf("PseudoMap:   l=%ld; c=%s\n", len, rdchars+1); */
  634.         rdchars[0] = '\'';
  635.         rdchars[len+1] = '\0';
  636.         /* previously : */
  637.         /* if (len == 1) {           */
  638.         /*      rdchars[0] = '\'';     */
  639.         /*      rdchars[len+1] = '\0'; */
  640.         /* } else {          */
  641.         /*      rdchars[0]     = '`';  */
  642.         /*      rdchars[len+1] = '\''; */
  643.         /* }             */
  644.  
  645. findhash_dummyfound:
  646.         if (using_hint)
  647.         *using_hint = TRUE;
  648.  
  649.         KS_COPY(&retdummy.key,ks);
  650.         retdummy.comm = rdchars;
  651. DEFMESSAGE( _KEY_unmapped_key, "unmapped Key!" )
  652.         retdummy.help = _KEY_unmapped_key;
  653.         return (&retdummy);
  654.     } /* if */
  655. /* printf("NOPseudoMap: r?=%s;\n", IsRawC(ks)?"Y":"N"); */
  656.  
  657.     }
  658. #endif /* NOT_DEF */
  659.     /* PATCH_NULL [02 Apr 1993] : we can not call that proc on unmapped keys yet <<< */
  660.  
  661.     return (NULL);
  662. } /* findhash */
  663.  
  664.  
  665.  
  666. /*****************************************************************************
  667.  
  668.     NAME
  669.     keyspectohash
  670.  
  671.     PARAMETER
  672.     KEYTABLE    *kt
  673.     const UBYTE *str
  674.  
  675.     RESULT
  676.     the Hashentry associated with
  677.     the name str
  678.  
  679.     RETURN
  680.     HASH *
  681.  
  682.     DESCRIPTION
  683.     transform str into a Hash-value and search for its entry
  684.  
  685.     NOTES
  686.     this routine uses findhash
  687.  
  688.     BUGS
  689.  
  690.     EXAMPLES
  691.  
  692.     SEE ALSO
  693.     findhash
  694.  
  695.     INTERNALS
  696.     falls es sich um einen gueltigen schluessel handelt,
  697.         finde eine passenden eintrag und
  698.         gib ihn aus
  699.     sonst gib NULL aus
  700.  
  701.     HISTORY
  702.     23-Jan-93  b_null created
  703.  
  704. ******************************************************************************/
  705.  
  706. HASH * keyspectohash (KEYTABLE * kt, const UBYTE *str)
  707. {
  708.     struct keyspec ks;
  709.  
  710.     if (get_codequal (str, &ks)) {
  711.     return (findhash (kt, &ks, 0, NULL));
  712.     } /* if is key */
  713.     return (NULL);
  714. } /* keyspectohash */
  715.  
  716.  
  717.  
  718. /*****************************************************************************
  719.  
  720.     NAME
  721.     keyspec2macro
  722.  
  723.     PARAMETER
  724.     KEYTABLE    * kt
  725.     const UBYTE * str
  726.  
  727.     RESULT
  728.     the macro-field of the Hashentry associated with
  729.     the name str
  730.  
  731.     RETURN
  732.     APTR
  733.  
  734.     DESCRIPTION
  735.     transform str into a Hash-value and search for its entry
  736.     then return its command-entry
  737.  
  738.     NOTES
  739.     this routine is splitted into
  740.     two minor ones by putting the searching
  741.     into another routine called findhash&keyspectohash
  742.  
  743.     BUGS
  744.  
  745.     EXAMPLES
  746.  
  747.     SEE ALSO
  748.     findhash
  749.  
  750.     INTERNALS
  751.     finde den passenden eintrag
  752.         und gib dessen comm aus
  753.  
  754.     HISTORY
  755.     14-Dec-92  b_null included
  756.     16-Dec-92  b_null splitted & documented
  757.  
  758. ******************************************************************************/
  759.  
  760. APTR keyspec2macro (KEYTABLE * kt, const UBYTE * str)
  761. {
  762.     HASH *hash;
  763.  
  764.     hash = keyspectohash (kt, str);
  765.     if (hash) {
  766.     return (hash->comm);
  767.     } /* if */
  768.     return (NULL);
  769. } /* keyspec2macro */
  770.  
  771.  
  772. /*****************************************************************************
  773.  
  774.     NAME
  775.     savekeys
  776.  
  777.     PARAMETER
  778.     KEYTABLE * kt
  779.     FILE *    fi
  780.  
  781.     RESULT
  782.     success:
  783.         RET_FAIL == error
  784.         RET_OK   == everything ok
  785.  
  786.     RETURN
  787.     int
  788.  
  789.     DESCRIPTION
  790.     write a special keymap file
  791.     or the keymap section of a file
  792.     such a section can be read with loadkeys
  793.  
  794.     NOTES
  795.     currently the keymap-section is in ascii
  796.     format - this may be changed to IFF
  797.     this function is separated from keysave for use in packages
  798.  
  799.     BUGS
  800.  
  801.     EXAMPLES
  802.  
  803.     SEE ALSO
  804.     loadkeys
  805.  
  806.     INTERNALS
  807.     schreibe einen header
  808.     gehe alle slots entlang und
  809.         schreibe alle eintraege der slots
  810.     schreibe einen footer
  811.  
  812.     HISTORY
  813.     14-Dec-92  b_null included
  814.     16-Dec-92  b_null documented
  815.  
  816. ******************************************************************************/
  817.  
  818. int savekeys (KEYTABLE * kt, FILE * fo)
  819. {
  820.     HASH * hash;
  821.     int    i;
  822.  
  823.     if (kt == NULL) {
  824.     return (RET_FAIL);
  825.     } /* if empty or missing table */
  826.  
  827.     fprintf(fo, "KEYLIST START\n");
  828.     for (i = 0; i < HASHSIZE; i++) {
  829.     for (hash = kt->hash[i]; hash; hash = hash->next) {
  830.         fprintf (fo, "\tKEY   %s\n", cqtoa (&hash->key));
  831. /* --- THAT BLOCK MUST BE CHANGED IF MACROS ARE MODIFIED */
  832.         if (hash->help)
  833.         fprintf (fo, "\t HELP %s\n", hash->help);
  834.         fprintf (fo, "\t COM  %s\n", hash->comm);
  835. /* --- THAT BLOCK MUST BE CHANGED IF MACROS ARE MODIFIED */
  836.     } /* for keys */
  837.     } /* for hashes */
  838.     fprintf(fo, "KEYLIST END\n");
  839.     return (RET_SUCC);
  840. } /* savekeys */
  841.  
  842.  
  843.  
  844. /*****************************************************************************
  845.  
  846.     NAME
  847.     loadkeys
  848.  
  849.     PARAMETER
  850.     KEYTABLE * kt
  851.     FILE *    fi
  852.     int  *    lineno
  853.  
  854.     RESULT
  855.     success:
  856.         RET_FAIL == error
  857.         RET_OK   == everything ok
  858.  
  859.     RETURN
  860.     int
  861.  
  862.     DESCRIPTION
  863.     read a special Keymap-File
  864.     or the Keymap-section of a file
  865.     which was created with savekeys
  866.  
  867.     NOTES
  868.     this function might call error()
  869.     this function is separated from keyload for use in packages
  870.     can not support "help" yet
  871.  
  872.     BUGS
  873.  
  874.     EXAMPLES
  875.  
  876.     SEE ALSO
  877.     savekeys
  878.  
  879.     INTERNALS
  880.     lese den header
  881.     solange alles gutging und der footer nicht erreicht wurde
  882.         lese nacheinander schluessel
  883.         und macro
  884.         falls eine Zeile nicht in diese Sequenz passt ABBRUCH
  885.  
  886.     das muss geaendert werden:
  887.     lese den header
  888.     solange alles gutging und der footer nicht erreicht wurde
  889.     lese  schluessel und
  890.     danach macro (und evtl help)
  891.         da die reihenfolge von macro und help variieren kann,
  892.            darf der naechste addhash erst durchgefuehrt werden beim naechsten KEY oder bei KEYLIST END
  893.  
  894.     HISTORY
  895.     14-Dec-92  b_null included
  896.     16-Dec-92  b_null documented
  897.  
  898. ******************************************************************************/
  899.  
  900. #define next_nonblank(buf) {while (*buf && *buf<33) buf++; }
  901.  
  902. int loadkeys (KEYTABLE * kt, FILE * fi, int * lineno)
  903. {
  904.     char * buf;
  905.     char   nkey   [128];
  906.     char   help   [128];
  907.     char   body   [LINE_LENGTH];
  908.  
  909.     if (kt == NULL) {
  910.     return (RET_FAIL);
  911.     } /* if empty or missing table */
  912.  
  913.     buf = getnextcomline (fi, lineno);
  914.  
  915.     if (!buf) {
  916.     SET_ABORTION( 1 );
  917.     return (RET_FAIL);
  918.     } /* if */
  919.     if (strncmp(buf, "KEYLIST START", 13) != 0) {
  920. DEFMESSAGE( _KEY_read_no_header, "No Keystart header" )
  921.     error  (_KEY_read_no_header);
  922.     return (RET_FAIL);
  923.     } /* if */
  924.  
  925.     nkey  [0] = 0;
  926.     help  [0] = 0;
  927.     body  [0] = 0;
  928.  
  929.     while (!IS_ABORTED()) {
  930.     buf = getnextcomline(fi, lineno);
  931. /* printf("read %s\n", buf); */
  932.     if (!buf) {
  933.         SET_ABORTION( 1 );
  934.         return (RET_FAIL);
  935.     } /* if */
  936.  
  937.     if (strncmp(buf, "KEYLIST END", 11) == 0) {
  938.         return (RET_SUCC);
  939.     } else if (strncmp(buf, "KEY ", 4) == 0) {
  940.         buf += 3;
  941.         next_nonblank(buf);
  942.         if (nkey[0] != 0) {
  943. DEFMESSAGE( _KEY_read_unex_new_key, "%s:\nDeclared Key w/out Body '%s'" )
  944.         error  (_KEY_read_unex_new_key, CommandName(), buf);
  945.         return (RET_FAIL);
  946.         } /* if */
  947.         strncpy(nkey, buf, 128);
  948. #ifndef NOT_DEF
  949.     } else if (strncmp(buf, "HELP", 4) == 0) {
  950.         buf += 4;
  951.         next_nonblank(buf);
  952.         if (nkey[0] == 0) {
  953. DEFMESSAGE( _KEY_read_unex_helpfield, "%s:\nDeclared Help w/out a Key" )
  954.         error  (_KEY_read_unex_helpfield, CommandName(), buf);
  955.         return (RET_FAIL);
  956.         } /* if */
  957.         strncpy(help, buf, 128);
  958. #endif
  959.     } else if (strncmp (buf, "COM", 3) == 0) {
  960.         buf += 3;
  961.         next_nonblank(buf);
  962.         if (nkey[0] == 0) {
  963. DEFMESSAGE( _KEY_read_unex_command_field, "<%s:\nDeclared Body w/out a Key" )
  964.         error  (_KEY_read_unex_command_field, CommandName());
  965.         return (RET_FAIL);
  966.         } /* if */
  967.         strncpy (body, buf, LINE_LENGTH);
  968.         mapkey  (kt, nkey, body, help[0]? help: NULL);
  969.         help[0] = 0;
  970.         nkey[0] = 0;
  971.     } else {
  972. DEFMESSAGE( _KEY_read_unknown_id, "%s:\nunknown identifier '%s'" )
  973.         error  (_KEY_read_unknown_id, CommandName(), buf);
  974.         return (RET_FAIL);
  975.     } /* if types */
  976.     } /* while not ready */
  977.     return (RET_FAIL);
  978. } /* loadkeys */
  979.  
  980.  
  981. /*****************************************************************************
  982.  
  983.     NAME
  984.     keysave
  985.  
  986.     PARAMETER
  987.     KEYTABLE * kt
  988.     char *    name
  989.  
  990.     RESULT
  991.     -/-
  992.  
  993.     RETURN
  994.     void
  995.  
  996.     DESCRIPTION
  997.     first abstraction of savekeys to single files:
  998.     handling of open&close
  999.  
  1000.     NOTES
  1001.  
  1002.     BUGS
  1003.  
  1004.     EXAMPLES
  1005.  
  1006.     SEE ALSO
  1007.     savekeys
  1008.  
  1009.     INTERNALS
  1010.     oeffne ein file
  1011.     falls das ging,
  1012.         lese die enthaltenen mappings
  1013.         und schliesse es
  1014.     sonst gib einen Fehler aus
  1015.  
  1016.     HISTORY
  1017.     14-Dec-92  b_null included
  1018.     16-Dec-92  b_null renamed & documented
  1019.  
  1020. ******************************************************************************/
  1021.  
  1022. #if 0
  1023. void keysave (KEYTABLE * kt, char * name)
  1024. {
  1025.     FILE * fo;
  1026.  
  1027.     if ((fo = fopen (name, "w"))) {
  1028.     savekeys (kt, fo);
  1029.     fclose (fo);
  1030.     } else {
  1031.     error ("%s:\nCan't open file %s for output", CommandName(), name);
  1032.     } /* if */
  1033. } /* keysave */
  1034. #endif
  1035.  
  1036. /*****************************************************************************
  1037.  
  1038.     NAME
  1039.     keyload
  1040.  
  1041.     PARAMETER
  1042.     KEYTABLE * kt
  1043.     char *    name
  1044.  
  1045.     RESULT
  1046.     -/-
  1047.  
  1048.     RETURN
  1049.     void
  1050.  
  1051.     DESCRIPTION
  1052.     first abstraction of loadkeys to single files:
  1053.     handling of open & close
  1054.  
  1055.     NOTES
  1056.  
  1057.     BUGS
  1058.  
  1059.     EXAMPLES
  1060.  
  1061.     SEE ALSO
  1062.     loadkeys
  1063.  
  1064.     INTERNALS
  1065.     oeffne ein file
  1066.     falls das ging,
  1067.         schreibe die aktuellen mappings hinein
  1068.         und schliesse es
  1069.     sonst gib einen Fehler aus
  1070.  
  1071.     HISTORY
  1072.     14-Dec-92  b_null included
  1073.     16-Dec-92  b_null renamed & documented
  1074.  
  1075. ******************************************************************************/
  1076.  
  1077. #if 0
  1078. void keyload (KEYTABLE * kt, char * name)
  1079. {
  1080.     FILE * fi;
  1081.     int    lineno = 0;
  1082.  
  1083.     if ((fi = fopen (name, "r"))) {
  1084.     dealloc_hash (kt);
  1085.     loadkeys (kt, fi, &lineno);
  1086.     fclose (fi);
  1087.     } else {
  1088.     error ("%s:\nCan't open file %s for input", CommandName(), name);
  1089.     } /* if */
  1090. } /* keyload */
  1091. #endif
  1092.  
  1093.  
  1094.  
  1095.  
  1096. /*****************************************************************************
  1097.  
  1098.     BASIC FUNCTIONS ON KEYTABLES :
  1099.  
  1100.     get, new, delete
  1101.  
  1102.     all keytables created with new_keytable are deleted at program termination
  1103.  
  1104. *****************************************************************************/
  1105.  
  1106. /*****************************************************************************
  1107.  
  1108.     NAME
  1109.     get_keytable
  1110.  
  1111.     PARAMETER
  1112.     char * name
  1113.  
  1114.     RESULT
  1115.     the keytable with the name name, if it is already existing
  1116.     else NULL
  1117.  
  1118.     RETURN
  1119.     KEYTABLE *
  1120.  
  1121.     DESCRIPTION
  1122.     search function on the hidden list of keytables
  1123.  
  1124.     NOTES
  1125.     useful only, if we are using multiple keytables
  1126.  
  1127.     BUGS
  1128.  
  1129.     EXAMPLES
  1130.  
  1131.     SEE ALSO
  1132.  
  1133.     INTERNALS
  1134.  
  1135.     HISTORY
  1136.     27 Jan 1993 b_null created
  1137.  
  1138. ******************************************************************************/
  1139.  
  1140. KEYTABLE * get_keytable (char * name)
  1141. {
  1142.     if (!KeyTables)
  1143.     return NULL;
  1144.  
  1145.     if (name == NULL)
  1146.     return (GetHead (KeyTables));
  1147.  
  1148.     return (KEYTABLE *)FindName(KeyTables, name);
  1149. } /* get_keytable */
  1150.  
  1151.  
  1152.  
  1153. /*****************************************************************************
  1154.  
  1155.     NAME
  1156.     delete_keytable
  1157.  
  1158.     PARAMETER
  1159.     KEYTABLE * kt
  1160.     int       force
  1161.  
  1162.     RESULT
  1163.     -/-
  1164.  
  1165.     RETURN
  1166.     void
  1167.  
  1168.     DESCRIPTION
  1169.     delete a full keytable
  1170.     that function does NOT dlete the last keytable,
  1171.     unless force is set to 1
  1172.  
  1173.     NOTES
  1174.     useful only, if we are using multiple keytables
  1175.  
  1176.     that function does NOT take care of any references to a keytable
  1177.     You must do that job on a higher abstraction-level
  1178.         (e.g. in keycom.c - for all ED's if )
  1179.  
  1180.     BUGS
  1181.  
  1182.     EXAMPLES
  1183.  
  1184.     SEE ALSO
  1185.  
  1186.     INTERNALS
  1187.     ausklinken aus der keytable-liste
  1188.     loeschen der hash-entries
  1189.     loeschen des namens
  1190.     loeschen des bodies
  1191.  
  1192.     HISTORY
  1193.     27 Jan 1993 b_null created
  1194.  
  1195. ******************************************************************************/
  1196.  
  1197. void delete_keytable (KEYTABLE * kt, int force)
  1198. {
  1199.     if (kt) {
  1200.     if ((!force) && (GetSucc(kt) == NULL) && (GetPred(kt) == NULL)) {
  1201.         return;
  1202.     } /* if */
  1203.  
  1204.     dealloc_hash (kt);
  1205. #if 0
  1206.     Remove        (&kt->node);
  1207.     DeallocFunc  (kt->node.ln_Name);
  1208. #else
  1209.     HL_Uninit(&kt->node);
  1210. #endif
  1211.     FreeFunc     (kt, sizeof(KEYTABLE));
  1212.     } /* if */
  1213. } /* delete_keytable */
  1214.  
  1215.  
  1216.  
  1217. /*****************************************************************************
  1218.  
  1219.     NAME
  1220.     new_keytable
  1221.  
  1222.     PARAMETER
  1223.     char * name
  1224.     int    defaults
  1225.  
  1226.     RESULT
  1227.     either a new keytable, if there is not already one with that name
  1228.     or the first keytable, that matches that name
  1229.     if we have to create a new one, we can set defaults to 1 to
  1230.     fill in the default-keytable
  1231.  
  1232.     RETURN
  1233.     KEYTABLE *
  1234.  
  1235.     DESCRIPTION
  1236.  
  1237.     NOTES
  1238.     useful only, if we are using multiple keytables
  1239.  
  1240.     if we can fill in only parts of the deafult-information,
  1241.     we do NOT fail
  1242.  
  1243.     BUGS
  1244.  
  1245.     EXAMPLES
  1246.  
  1247.     SEE ALSO
  1248.  
  1249.     INTERNALS
  1250.  
  1251.     HISTORY
  1252.     27 Jan 1993 b_null created
  1253.  
  1254. ******************************************************************************/
  1255.  
  1256. KEYTABLE * new_keytable (char * name, int defaults)
  1257. {
  1258.     KEYTABLE * kt;
  1259.  
  1260.     if (!KeyTables)
  1261.     return NULL;
  1262.  
  1263.     if ((kt = get_keytable(name))) {
  1264.     return (kt);
  1265.     } /* if */
  1266.  
  1267.     kt = AllocFunc (sizeof(KEYTABLE), MEMF_ANY);
  1268.     if (kt == NULL) {
  1269.     return (NULL);
  1270.     } /* if */
  1271.  
  1272.     bzero (kt, sizeof(KEYTABLE));
  1273. #if 0
  1274.     kt->node.ln_Name = DupFunc (name, MEMF_ANY);
  1275.     if (kt->node.ln_Name == NULL) {
  1276.     FreeFunc (kt, sizeof (KEYTABLE));
  1277.     return (NULL);
  1278.     } /* if */
  1279.  
  1280.     AddTail (KeyTables, &kt->node);
  1281. #else
  1282.     if (HL_Init(&kt->node, name, KeyRoot, HLF_SYSNODE) != HL_OK) {
  1283.     FreeFunc (kt, sizeof (KEYTABLE));
  1284.     return NULL;
  1285.     } /* if */
  1286. #endif
  1287.     if (defaults) {
  1288.     resethash (kt);
  1289.     } /* if */
  1290.  
  1291.     return (kt);
  1292. } /* new_keytable */
  1293.  
  1294.  
  1295.  
  1296. /*****************************************************************************
  1297.  
  1298.     NAME
  1299.     init_keytables
  1300.     exit_keytables
  1301.  
  1302.     PARAMETER
  1303.     void
  1304.  
  1305.     RESULT
  1306.     -/-
  1307.  
  1308.     RETURN
  1309.     void
  1310.  
  1311.     DESCRIPTION
  1312.     init and exit functions for keytables
  1313.  
  1314.     NOTES
  1315.     useful only, if we are using multiple keytables
  1316.  
  1317.     THESE are __AUTOEXIT/__AUTOEXIT - functions !!!!
  1318.  
  1319.     HISTORY
  1320.     27 Jan 1993 b_null created
  1321.  
  1322. ******************************************************************************/
  1323.  
  1324.  
  1325. DEFAUTOINIT( init_keytables )
  1326. {
  1327. //puts (__FILE__);
  1328.     init_kb();
  1329. #if 0
  1330.     KeyTables = &_KeyTables;
  1331.     NewList     (KeyTables);
  1332. #else
  1333.     KeyRoot   = HL_SystemList("*Keytables*");
  1334.     KeyTables = HL_LockSubs(KeyRoot);
  1335.     HL_UnlockSubs(KeyRoot);
  1336. #endif
  1337.     new_keytable ("default",1);
  1338. } /* init_keytables */
  1339.  
  1340.  
  1341. DEFAUTOEXIT( exit_keytables )
  1342. {
  1343.     KEYTABLE * kt;
  1344.  
  1345.     if (KeyTables)
  1346.     while ((kt = GetHead (KeyTables)))
  1347.         delete_keytable (kt, 1);
  1348. #if 1
  1349.     HL_Dispose(KeyRoot);
  1350. #endif
  1351. } /* exit_keytables */
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357. /******************************************************************************
  1358. *****  ENDE keytables.c
  1359. ******************************************************************************/
  1360.